/**
 * Ship.java
 */
package edu.gatech.startrader.ship;

import java.util.ArrayList;
import java.util.List;

import edu.gatech.startrader.player.Player;
import edu.gatech.startrader.trade.Cargo;
import edu.gatech.startrader.trade.TradeGood;

/**
 * Ship Class
 * This class sets up the ship the player uses
 * @author Team Bamf (Team 30)
 * @version 1.0
 */
public final class Ship {
	/**
	 * type of ship
	 */
	private ShipType type;
	
	/**
	 * the amount of hull the ship has
	 */
	private int hull;
	
	/**
	 * the amount of fuel the ship has
	 */
	private int fuel;
	
	/**
	 * whether or not the ship has an escape pod
	 */
	private boolean escapePod;
	
	/**
	 * whether or not the ship has insurance
	 */
	private boolean insurance;
	
	/**
	 * list of weapons the ship has
	 */
	private final List<Weapon> weapons;
	
	/**
	 * list of shields the ship has
	 */
	private final List<Shield> shields;
	
	/**
	 * the list of gadgets the ship has
	 */
	private final List<Gadget> gadgets;
	
	/**
	 * the cargo the ship has
	 */
	private Cargo cargo;
	
	/**
	 * The ratio of a ship's price the player has to pay each turn
	 */
	private final double insuranceRatio;
	
	/**
	 * Ship Constructor
	 * This Constructor sets up the ship with a ship type
	 * @param type the type of ship
	 */
	public Ship(ShipType type) {
		weapons = new ArrayList<Weapon>();
		shields = new ArrayList<Shield>();
		gadgets = new ArrayList<Gadget>();
		insuranceRatio = 0.1;
		setType(type);
	}
	
	/**
	 * fillCargo method
	 * This method fills the cargo with a specified amount of a resource
	 * @param type the kind of resource
	 * @param amount the integer amount of the resource
	 */
	public void fillCargo(TradeGood type, int amount) {
		cargo.addCargo(type, amount);
	}
	
	/**
	 * emptyCargo method
	 * This method empties a specified amount of a resource
	 * @param type the kind of resource
	 * @param amount the integer amount of the resource
	 */
	public void emptyCargo(TradeGood type, int amount) {
		cargo.removeCargo(type, amount);
	}
	
	/**
	 * remainingCargoSpace method
	 * This method gets the amount of cargo space that is left
	 * @return cargo space left
	 */
	public int remainingCargoSpace() {
		return cargo.checkRemainingCargoSpace();
	}
	
	/**
	 * getType Method
	 * This method returns the type of a ship
	 * @return ShipType the type of ship
	 */
	public ShipType getType() {
		return type;
	}
	
	/**
	 * setType method
	 * This method sets the type of ship
	 * @param shipType ShipType the type of ship
	 */
	public void setType(ShipType shipType) {
		type = shipType;
		hull = type.getMaxHull();
		fuel = type.getMaxFuel();
		cargo = new Cargo(type.getBaseCargoSpace());
	}
	
	/**
	 * getFuel method
	 * This method returns the amount of fuel in the ship
	 * @return amount of fuel
	 */
	public int getFuel() {
		return fuel;
	}
	
	/**
	 * getMaxFuel method
	 * This method returns the maximum amount of fuel a ship can carry
	 * @return amount of fuel
	 */
	public int getMaxFuel() {
		return type.getMaxFuel();
	}
	
	/**
	 * getHull method
	 * This method returns the health of the hull of the ship
	 * @return health of the hull
	 */
	public int getHull() {
		return hull;
	}
	
	/**
	 * getMaxHull method
	 * This method returns the maximum health of the hull of the ship
	 * @return max amount of hull health
	 */
	public int getMaxHull() {
		return type.getMaxHull();
	}
	
	/**
	 * getWeapons method
	 * This method gets the weapons the ship has equipped
	 * @return the weapons on the ship
	 */
	public Weapon[] getWeapons() {
		return (Weapon[]) (weapons.toArray());
	}
	
	/**
	 * getShields method
	 * This method returns the shields the ship has equipped
	 * @return the shields on the ship
	 */
	public Shield[] getShields() {
		return (Shield[]) (shields.toArray());
	}
	
	/**
	 * getGadgets method
	 * This method returns the gadgets that the ship has equipped
	 * @return the gadgets on the ship
	 */
	public Gadget[] getGadgets() {
		return (Gadget[]) (gadgets.toArray());
	}
	
	/**
	 * getCargo method
	 * This method returns the cargo
	 * @return the cargo
	 */
	public Cargo getCargo() {
		return cargo;
	}
	
	/**
	 * hasEscapePod method
	 * This method checks to see if the ship has an escape pod equipped
	 * @return boolean true if the ship has an escape pod, false if not
	 */
	public boolean hasEscapePod() {
		return escapePod;
	}
	
	/**
	 * installEscapePod method
	 * This method installs an escape pod into the ship
	 */
	public void installEscapePod() {
		escapePod = true;
	}
	
	/**
	 * isInsured method
	 * This method checks to see if the ship is insured
	 * @return boolean true if the ship is insured, false if not
	 */
	public boolean isInsured() {
		return insurance;
	}
	
	/**
	 * insure method
	 * This method insures the ship
	 */
	public void insure() {
		insurance = true;
	}
	
	/**
	 * payInsurance method
	 * This method pays the insurance price
	 * @param p the player that will pay the insurance price
	 */
	public void payInurance(Player p) {
		p.pay((int) Math.round((type.getPrice() * insuranceRatio)));
	}
	
	/**
	 * refuel method
	 * This method refuels the ship
	 */
	public void refuel() {
		fuel = getMaxFuel();
	}
	
	/**
	 * removeFuel method
	 * This method removes an amount of fuel from the ship
	 * @param amt the amount of fuel to remove from the ship
	 */
	public void useFuel(int amt) {
		fuel -= amt;
	}
	
	/**
	 * repair method
	 * This method repairs the ship
	 */
	public void repair() {
		hull = type.getMaxHull();
	}
	
	/**
	 * addWeapon method
	 * This method adds a weapon to the ship
	 * @param w the weapon that is to be added
	 */
	public void addWeapon(Weapon w) {
		if(weapons.size() + 1 > type.getWeaponSlots()) {
			throw new IllegalArgumentException("Ship cannot hold any more Weapons!");
		}
		weapons.add(w);
	}
	
	/**
	 * addShield method
	 * This method adds a shield to the ship
	 * @param s shield that will be added
	 */
	public void addShield(Shield s) {
		if(shields.size() + 1 > type.getShieldSlots()) {
			throw new IllegalArgumentException("Ship cannot hold any more Shields!");
		}
		shields.add(s);
	}
	
	/**
	 * addGadget method
	 * This method adds a gadget to the ship
	 * @param g gadget that will be added
	 */
	public void addGadget(Gadget g) {
		if(gadgets.size() + 1 > type.getGadgetSlots()) {
			throw new IllegalArgumentException("Ship cannot hold any more Gadgets!");
		}
		gadgets.remove(g);
	}
	
	/**
	 * removeWeapon method
	 * This method will remove a weapon from the ship
	 * @param w weapon to be removed
	 */
	public void removeWeapon(Weapon w) {
		weapons.remove(w);
	}
	
	/**
	 * removeShield method
	 * This method removes a shield from the ship
	 * @param s the ship to be removed
	 */
	public void removeShield(Shield s) {
		shields.remove(s);
	}
	
	/**
	 * removeGadget method
	 * This method removes a gadget from the ship
	 * @param g gadget to be removed
	 */
	public void removeGadget(Gadget g) {
		gadgets.remove(g);
	}
	
	/**
	 * toString method
	 * This method writes the type of ship to a string
	 * @return String 
	 */
	public String toString(){
		return type.toString();
	}
	
	/**
	 * Collects the number of cargo holds holding the specific resource
	 * @param resource the resource we are checking for
	 * @return the number of cargo hold holding that resource
	 */
	public int getCargoItems(TradeGood resource) {
		return cargo.getItems(resource);
	}
}
